using System.Text;
using System;
using System.Data;
using System.Data.SqlClient;
using Csla;
using Csla.Data;
using Csla.Validation;
using BA.DAL;
using BA;

namespace BlazeApps.Library.Forum
{ 
	[Serializable()] 
	public class Forum : Csla.BusinessBase<Forum>
	{
        private BlazeApps.Library.ConfigSettings Config = new BlazeApps.Library.ConfigSettings();
        private BA.DAL.DBUtility DAL = new BA.DAL.DBUtility();
        private Procedures Procs = new Procedures();

		#region Business Properties and Methods

		//declare members
		private Guid _forumID = Guid.NewGuid();
		private Guid _categoryID = Guid.Empty;
		private string _forumName = string.Empty;
		private string _description = string.Empty;
		private int _sortOrder = 0;
		private Guid _lastUserID = Guid.Empty;
        private Boolean _Locked = false;
        private Boolean _Moderated = false;

		[System.ComponentModel.DataObjectField(true, false)]
		public Guid ForumID
		{
			get
			{
				CanReadProperty("ForumID", true);
				return _forumID;
			}
		}

		public Guid CategoryID
		{
			get
			{
				CanReadProperty("CategoryID", true);
				return _categoryID;
			}
			set
			{
				CanWriteProperty("CategoryID", true);
				if (!_categoryID.Equals(value))
				{
					_categoryID = value;
					PropertyHasChanged("CategoryID");
				}
			}
		}

		public string ForumName
		{
			get
			{
				CanReadProperty("ForumName", true);
				return _forumName;
			}
			set
			{
				CanWriteProperty("ForumName", true);
				if (value == null) value = string.Empty;
				if (!_forumName.Equals(value))
				{
					_forumName = value;
					PropertyHasChanged("ForumName");
				}
			}
		}

		public string Description
		{
			get
			{
				CanReadProperty("Description", true);
				return _description;
			}
			set
			{
				CanWriteProperty("Description", true);
				if (value == null) value = string.Empty;
				if (!_description.Equals(value))
				{
					_description = value;
					PropertyHasChanged("Description");
				}
			}
		}

		public int SortOrder
		{
			get
			{
				CanReadProperty("SortOrder", true);
				return _sortOrder;
			}
			set
			{
				CanWriteProperty("SortOrder", true);
				if (!_sortOrder.Equals(value))
				{
					_sortOrder = value;
					PropertyHasChanged("SortOrder");
				}
			}
		}

		public Guid LastUserID
		{
			get
			{
				CanReadProperty("LastUserID", true);
				return _lastUserID;
			}
			set
			{
				CanWriteProperty("LastUserID", true);
				if (!_lastUserID.Equals(value))
				{
					_lastUserID = value;
					PropertyHasChanged("LastUserID");
				}
			}
		}

        public Boolean Locked
        {
            get
            {
                return _Locked;
            }
            set
            {
                CanWriteProperty("Locked", true);
                if (!_Locked.Equals(value))
                {
                    _Locked = value;
                    PropertyHasChanged("Locked");
                }
            }
        }

        public Boolean Moderated
        {
            get
            {
                return _Moderated;
            }
            set
            {
                CanWriteProperty("Moderated", true);
                if(!_Moderated.Equals(value))
                {
                    _Moderated = value;
                    PropertyHasChanged("Moderated");
                }
            }
        }
 
		protected override object GetIdValue()
		{
			return _forumID;
		}

		#endregion //Business Properties and Methods

		#region Validation Rules
		private void AddCustomRules()
		{
			//add custom/non-generated rules here...
		}

		private void AddCommonRules()
		{
			//
			// ForumName
			//
			ValidationRules.AddRule(CommonRules.StringRequired, "ForumName");
			//
			// Description
			//
			ValidationRules.AddRule(CommonRules.StringRequired, "Description");
		}

		protected override void AddBusinessRules()
		{
			AddCommonRules();
			AddCustomRules();
		}
		#endregion //Validation Rules

		#region Authorization Rules
		protected override void AddAuthorizationRules()
		{
			//TODO: Define authorization rules in Forum
			//AuthorizationRules.AllowRead("ForumID", "ForumReadGroup");
			//AuthorizationRules.AllowRead("CategoryID", "ForumReadGroup");
			//AuthorizationRules.AllowRead("ForumName", "ForumReadGroup");
			//AuthorizationRules.AllowRead("Description", "ForumReadGroup");
			//AuthorizationRules.AllowRead("SortOrder", "ForumReadGroup");
			//AuthorizationRules.AllowRead("TopicsCount", "ForumReadGroup");
			//AuthorizationRules.AllowRead("PostsCount", "ForumReadGroup");
			//AuthorizationRules.AllowRead("LastPostBy", "ForumReadGroup");
			//AuthorizationRules.AllowRead("LastUserID", "ForumReadGroup");
			//AuthorizationRules.AllowRead("LastPostDate", "ForumReadGroup");
			//AuthorizationRules.AllowRead("LastPostDateString", "ForumReadGroup");

			//AuthorizationRules.AllowWrite("CategoryID", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("ForumName", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("Description", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("SortOrder", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("TopicsCount", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("PostsCount", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("LastPostBy", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("LastUserID", "ForumWriteGroup");
			//AuthorizationRules.AllowWrite("LastPostDateString", "ForumWriteGroup");
		}


		public static bool CanGetObject()
		{
			//TODO: Define CanGetObject permission in Forum
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("ForumViewGroup"))
			//	return true;
			//return false;
		}

		public static bool CanAddObject()
		{
			//TODO: Define CanAddObject permission in Forum
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("ForumAddGroup"))
			//	return true;
			//return false;
		}

		public static bool CanEditObject()
		{
			//TODO: Define CanEditObject permission in Forum
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("ForumEditGroup"))
			//	return true;
			//return false;
		}

		public static bool CanDeleteObject()
		{
			//TODO: Define CanDeleteObject permission in Forum
			return true;
			//if (Csla.ApplicationContext.User.IsInRole("ForumDeleteGroup"))
			//	return true;
			//return false;
		}
		#endregion //Authorization Rules

		#region Factory Methods
		private Forum()
		{ /* require use of factory method */ }

		public static Forum NewForum()
		{
			if (!CanAddObject())
				throw new System.Security.SecurityException("User not authorized to add a Forum");
			return DataPortal.Create<Forum>();
		}

		public static Forum GetForum(Guid forumID)
		{
			if (!CanGetObject())
				throw new System.Security.SecurityException("User not authorized to view a Forum");
			return DataPortal.Fetch<Forum>(new Criteria(forumID));
		}

		public static void DeleteForum(Guid forumID)
		{
			if (!CanDeleteObject())
				throw new System.Security.SecurityException("User not authorized to remove a Forum");
			DataPortal.Delete(new Criteria(forumID));
		}

		public override Forum Save()
		{
			if (IsDeleted && !CanDeleteObject())
				throw new System.Security.SecurityException("User not authorized to remove a Forum");
			else if (IsNew && !CanAddObject())
				throw new System.Security.SecurityException("User not authorized to add a Forum");
			else if (!CanEditObject())
				throw new System.Security.SecurityException("User not authorized to update a Forum");

			return base.Save();
		}

		#endregion //Factory Methods

		#region Data Access

		#region Criteria

		[Serializable()]
		private class Criteria
		{
			public Guid ForumID;

			public Criteria(Guid forumID)
			{
				this.ForumID = forumID;
			}
		}

		#endregion //Criteria

		#region Data Access - Create
		[RunLocal]
		protected override void DataPortal_Create()
		{
			ValidationRules.CheckRules();
		}

		#endregion //Data Access - Create

		#region Data Access - Fetch
        private void DataPortal_Fetch(Criteria criteria)
        {
            ExecuteFetch(criteria);
        }

        private void ExecuteFetch(Criteria criteria)
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            DAL.AddParameter("@ForumID", criteria.ForumID);

            using(SafeDataReader dr = new SafeDataReader(DAL.ExecuteReader(Procs.GetForumByForumID.ToString().Trim(), CommandType.Text, ConnectionState.Open)))
            {
                FetchObject(dr);
                ValidationRules.CheckRules();

                //load child object(s)
                FetchChildren(dr);
            }
        }

		private void FetchObject(SafeDataReader dr)
		{
			dr.Read();
			_forumID = dr.GetGuid("ForumID");
			_categoryID = dr.GetGuid("CategoryID");
			_forumName = dr.GetString("ForumName");
			_description = dr.GetString("Description");
			_sortOrder = dr.GetInt32("SortOrder");
			_lastUserID = dr.GetGuid("LastUserID");
            _Locked = dr.GetBoolean("Locked");
            _Moderated = dr.GetBoolean("Moderated");
		}

		private void FetchChildren(SafeDataReader dr)
		{
		}
		#endregion //Data Access - Fetch

		#region Data Access - Insert
        protected override void DataPortal_Insert()
        {
            ExecuteInsert();
        }

        private void ExecuteInsert()
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddInsertParameters(ref DAL);

            DAL.ExecuteNonQuery(Procs.InsertForum.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void AddInsertParameters(ref BA.DAL.DBUtility DAL)
		{
			DAL.AddParameter("@ForumID", _forumID);
			DAL.AddParameter("@CategoryID", _categoryID);
			DAL.AddParameter("@ForumName", _forumName);
			DAL.AddParameter("@Description", _description);
			DAL.AddParameter("@SortOrder", _sortOrder);
			DAL.AddParameter("@LastUserID", _lastUserID);
            DAL.AddParameter("@Locked", _Locked);
            DAL.AddParameter("@Moderated", _Moderated);
            
		}
		#endregion //Data Access - Insert

		#region Data Access - Update
        protected override void DataPortal_Update()
        {
            if (base.IsDirty)
            {
                ExecuteUpdate();
            }
        }

        private void ExecuteUpdate()
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddUpdateParameters(ref DAL);

            DAL.ExecuteNonQuery(Procs.UpdateForum.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void AddUpdateParameters(ref BA.DAL.DBUtility DAL)
		{
			DAL.AddParameter("@ForumID", _forumID);
			DAL.AddParameter("@CategoryID", _categoryID);
			DAL.AddParameter("@ForumName", _forumName);
			DAL.AddParameter("@Description", _description);
			DAL.AddParameter("@SortOrder", _sortOrder);
			DAL.AddParameter("@LastUserID", _lastUserID);
            DAL.AddParameter("@Locked", _Locked);
            DAL.AddParameter("@Moderated", _Moderated);
		}

		private void UpdateChildren(SqlConnection cn)
		{
		}
		#endregion //Data Access - Update

		#region Data Access - Delete
        protected override void DataPortal_DeleteSelf()
        {
            DataPortal_Delete(new Criteria(_forumID));
        }

        private void DataPortal_Delete(Criteria criteria)
        {
            ExecuteDelete(criteria);
            DeleteModerators(criteria);
        }

        private void ExecuteDelete(Criteria criteria)
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddDeleteParameters(ref DAL, criteria);

            DAL.ExecuteNonQuery(Procs.DeleteForum.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void DeleteModerators(Criteria criteria)
        {
            DAL.CreateDBObjects(Config.ConnectionString, Config.Provider);

            AddDeleteParameters(ref DAL, criteria);

            DAL.ExecuteNonQuery(Procs.DeleteForumModeratorsByForumID.ToString().Trim(), CommandType.Text, ConnectionState.Open);
        }

        private void AddDeleteParameters(ref BA.DAL.DBUtility DAL, Criteria criteria)
        {
            DAL.AddParameter("@ForumID", criteria.ForumID);
        }

		#endregion //Data Access - Delete
		#endregion //Data Access
	}
}
